/*
 * PDLogger
 * 
 * Copyright (c) 2012, Zoujie Wu <yibn2008@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 * 
 *   * Redistributions of source code must retain the above copyright notice, this 
 *     list of conditions and the following disclaimer.
 *   
 *   * Redistributions in binary form must reproduce the above copyright notice, 
 *     this list of conditions and the following disclaimer in the documentation 
 *     and/or other materials provided with the distribution.
 *   
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/* $Id$ */

#ifndef PHP_PDLOGGER_H
#define PHP_PDLOGGER_H

/* define module entry */
extern zend_module_entry pdlogger_module_entry;
#define phpext_pdlogger_ptr &pdlogger_module_entry

#ifdef PHP_WIN32
#	define PDL_API __declspec(dllexport)
#elif defined(__GNUC__) && __GNUC__ >= 4
#	define PDL_API __attribute__ ((visibility("default")))
#else
#	define PDL_API
#endif

#ifdef ZTS
#include "TSRM.h"
#endif

/* define common PDL constant */
#define PDL_NAME				"PDLogger"
#define PDL_AUTHOR				"Zoujie Wu"
#define PDL_VERSION				"1.0.0"
#define PDL_URL					"http://pdlogger.googlecode.com"
#define PDL_COPYRIGHT			"Copyright (c) 2012"
#define PDL_INIT_RECORD_NUM		32
#define PDL_INIT_FUNC_NUM		16
#define PDL_DEFAULT_PERIOD		24 * 60 * 60

#define MICRO_IN_SEC 1000000.00

/* define log error level constant */
#define PDL_LV_INFO			(1<<0L)
#define PDL_LV_WARNING		(1<<1L)
#define PDL_LV_ERROR		(1<<2L)
#define PDL_LV_EXCEPTION	(1<<3L)
#define PDL_LV_DEBUG		(1<<4L)

#define PDL_CHECK_ENABLE \
	do { \
		if (!PDL_G(enable)) { \
			return; \
		} \
	} while (0)

#define PDL_CLEAN_CF_CB(cf_cb) \
	do { \
		if (cf_cb.record_cb) { \
			zval_ptr_dtor(&cf_cb.record_cb); \
		} \
		if (cf_cb.header_cb) { \
			zval_ptr_dtor(&cf_cb.header_cb); \
		} \
		if (cf_cb.delimiter) { \
			efree(cf_cb.delimiter); \
			cf_cb.delimiter_len = 0; \
		} \
	} while (0)

typedef struct _pdl_time_t {
	long	sec;
	long	usec;
} pdl_time_t;

typedef struct _pdl_cf_cb_t {
	zval *record_cb;		/* record format callback */
	zval *header_cb;		/* header format callback */
	char *delimiter;		/* delimiter of different records */
	uint delimiter_len;		/* delimiter length */
} pdl_cf_cb_t;

/* define record item struct */
typedef struct _pdl_record_t {
	int			level;		/* record level */
	pdl_time_t	time;		/* record time */
	char		*label;		/* record label */
	char		*msg;		/* record message */
	zval		*data;		/* record data */
	char		*file;		/* record file */
	uint		line;		/* record line */
} pdl_record_t;

typedef struct _pdl_wf_t {
	char	*class_name;	/* class name */
	char	*func_name;		/* function name */
	zval	*watch_cb;		/* watch function callback */
} pdl_wf_t;

/* define common internal API */
PDL_API zend_bool pdl_start(zend_bool reset TSRMLS_DC);
PDL_API void pdl_stop(zend_bool write TSRMLS_DC);
PDL_API void pdl_record_dtor(pdl_record_t **record_p);
PDL_API void pdl_wf_dtor(pdl_wf_t *wf);
PDL_API const char* pdl_level_name(int level);
PDL_API pdl_time_t pdl_get_curr_time();
PDL_API double pdl_calc_interval(pdl_time_t from);

/* {{{ ARG_INFO
 */
ZEND_BEGIN_ARG_INFO(pdl_start_arginfo, 0)
	ZEND_ARG_INFO(0, reset)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO(pdl_stop_arginfo, 0)
	ZEND_ARG_INFO(0, stop)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO(pdl_enable_arginfo, 0)
	ZEND_ARG_INFO(0, enable)
ZEND_END_ARG_INFO()
/* }}} */

/* define common API */
PHP_FUNCTION(pdl_start);
PHP_FUNCTION(pdl_started);
PHP_FUNCTION(pdl_stop);
PHP_FUNCTION(pdl_reset);
PHP_FUNCTION(pdl_enable);
PHP_FUNCTION(pdl_start_time);
PHP_FUNCTION(pdl_records_num);

/* define init & shutdown functions */
PHP_MINIT_FUNCTION(pdlogger);
PHP_MSHUTDOWN_FUNCTION(pdlogger);
PHP_RINIT_FUNCTION(pdlogger);
PHP_RSHUTDOWN_FUNCTION(pdlogger);
PHP_MINFO_FUNCTION(pdlogger);

/* define module globals */
ZEND_BEGIN_MODULE_GLOBALS(pdlogger)
	zend_bool		started;			/* is PDLogger started */
	zend_bool		enable;				/* is PDLogger enabled */
	zend_bool		has_written;		/* has the record written */
	pdl_time_t		start_time;			/* request start time */
	int				format;				/* PDLogger output format */
	pdl_cf_cb_t		cf_cb;				/* PDLogger custom format callback info */
	int				watch;				/* PDLogger watch items */
	HashTable		watch_funcs;		/* PDLogger watch functions */
	HashTable		override_funcs;		/* PDLogger override functions */
	HashTable		records;			/* PDLogger records */
	char			*output_dir;		/* PDLogger output dir */
	char			*log_ext;			/* ext name of custom log file */
	int				period;				/* log changing period (sec) of log file */
ZEND_END_MODULE_GLOBALS(pdlogger)

#ifdef ZTS
#define PDL_G(v) TSRMG(pdlogger_globals_id, zend_pdlogger_globals *, v)
#else
#define PDL_G(v) (pdlogger_globals.v)
#endif

/* enable pdlogger_globals in other pdl_* files */
ZEND_EXTERN_MODULE_GLOBALS(pdlogger)

#endif	/* PHP_PDLOGGER_H */


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim<600: noet sw=4 ts=4
 */
